package edu.luc.cs.trull.demo.wristwatch;

import java.beans.PropertyChangeEvent;
import edu.luc.cs.trull.Cycle;
import edu.luc.cs.trull.EmitComponent;

/**
 * alarmmode =
 *   cycle RESET
 *     setHour
 *     setMinute
 *     setDay
 *     setMonth
 */
public class AlarmMode extends Cycle implements EventLabels {
	public AlarmMode(AlarmModel d) {
  		setCycleEvent(RESET);
		d.setAlarmTime1( 120 );
		d.setAlarmTime2( 300 );
		d.setAlarmTime3( 600 );
  		addComponent(new SetAlarmHour1(d));
		addComponent(new SetAlarmMinute1(d));
		addComponent(new SetAlarmHour2(d));
		addComponent(new SetAlarmMinute2(d));
		addComponent(new SetAlarmHour3(d));
		addComponent(new SetAlarmMinute3(d));
	}
}

class SetAlarmHour1 extends EmitComponent implements EventLabels, DateConstants {

	private AlarmModel alarm;
	
	public SetAlarmHour1(AlarmModel alarm) {
		this.alarm = alarm;
	}

	public void start(PropertyChangeEvent incoming) { 
		scheduleEvent(ALARM_HOUR_1);
		scheduleEvent(NOW, new Integer(alarm.getAlarmTime1() / SEC_PER_MIN));
	}
	
	public void stop() { }

	public void propertyChange(final PropertyChangeEvent event) {
		if (START.equals(event.getPropertyName())) {
			alarm.setAlarmTime1((alarm.getAlarmTime1() + SEC_PER_HOUR) % SEC_PER_DAY);					
			scheduleEvent(NOW, new Integer(alarm.getAlarmTime1() / SEC_PER_MIN));
		}
	}
}

class SetAlarmHour2 extends EmitComponent implements EventLabels, DateConstants {

	private AlarmModel alarm;
	
	public SetAlarmHour2(AlarmModel alarm) {
		this.alarm = alarm;
	}

	public void start(PropertyChangeEvent incoming) { 
		scheduleEvent(ALARM_HOUR_2);
		scheduleEvent(NOW, new Integer(alarm.getAlarmTime2() / SEC_PER_MIN));
	}
	
	public void stop() { }

	public void propertyChange(final PropertyChangeEvent event) {
		if (START.equals(event.getPropertyName())) {
			alarm.setAlarmTime2 ((alarm.getAlarmTime2() + SEC_PER_HOUR) % SEC_PER_DAY);					
			scheduleEvent(NOW, new Integer(alarm.getAlarmTime2() / SEC_PER_MIN));
		}
	}
}

class SetAlarmHour3 extends EmitComponent implements EventLabels, DateConstants {

	private AlarmModel alarm;
	
	public SetAlarmHour3(AlarmModel alarm) {
		this.alarm = alarm;
	}

	public void start(PropertyChangeEvent incoming) { 
		scheduleEvent(ALARM_HOUR_3);
		scheduleEvent(NOW, new Integer(alarm.getAlarmTime3() / SEC_PER_MIN));
	}
	
	public void stop() { }

	public void propertyChange(final PropertyChangeEvent event) {
		if (START.equals(event.getPropertyName())) {
			alarm.setAlarmTime3 ((alarm.getAlarmTime2() + SEC_PER_HOUR) % SEC_PER_DAY);					
			scheduleEvent(NOW, new Integer(alarm.getAlarmTime3() / SEC_PER_MIN));
		}
	}
}


/**
 * ( emit MIN
 *     ; emit NOW(time / 60)
 *     ; loop
 *         START -> emit NOW(time = time / 3600 * 3600 + (time + 60) % ...)
 *     )
 */
class SetAlarmMinute1 extends EmitComponent implements EventLabels, DateConstants {
	
	private AlarmModel alarm;
	
	public SetAlarmMinute1(AlarmModel alarm) {
		this.alarm = alarm;
	}

	public void start(PropertyChangeEvent incoming) { 
		scheduleEvent(ALARM_MIN_1);
		scheduleEvent(NOW, new Integer(alarm.getAlarmTime1() / SEC_PER_MIN));
	}
	
	public void stop() { }

	public void propertyChange(final PropertyChangeEvent event) {
		if (START.equals(event.getPropertyName())) {
			alarm.setAlarmTime1 (alarm.getAlarmTime1() / SEC_PER_HOUR * SEC_PER_HOUR
					+ (alarm.getAlarmTime1() + SEC_PER_MIN) % SEC_PER_HOUR);
			scheduleEvent(NOW, new Integer(alarm.getAlarmTime1() / SEC_PER_MIN));
		}
	}
}

class SetAlarmMinute2 extends EmitComponent implements EventLabels, DateConstants {
	
	private AlarmModel alarm;
	
	public SetAlarmMinute2(AlarmModel alarm) {
		this.alarm = alarm;
	}


	public void start(PropertyChangeEvent incoming) { 
		scheduleEvent(ALARM_MIN_2);
		scheduleEvent(NOW, new Integer(alarm.getAlarmTime2() / SEC_PER_MIN));
	}
	
	public void stop() { }

	public void propertyChange(final PropertyChangeEvent event) {
		if (START.equals(event.getPropertyName())) {
			alarm.setAlarmTime2 (alarm.getAlarmTime2() / SEC_PER_HOUR * SEC_PER_HOUR
					+ (alarm.getAlarmTime2() + SEC_PER_MIN) % SEC_PER_HOUR);
			scheduleEvent(NOW, new Integer(alarm.getAlarmTime2() / SEC_PER_MIN));
		}
	}
}

class SetAlarmMinute3 extends EmitComponent implements EventLabels, DateConstants {
	
	private AlarmModel alarm;
	
	public SetAlarmMinute3(AlarmModel alarm) {
		this.alarm = alarm;
	}


	public void start(PropertyChangeEvent incoming) { 
		scheduleEvent(ALARM_MIN_3);
		scheduleEvent(NOW, new Integer(alarm.getAlarmTime3() / SEC_PER_MIN));
	}
	
	public void stop() { }

	public void propertyChange(final PropertyChangeEvent event) {
		if (START.equals(event.getPropertyName())) {
			alarm.setAlarmTime3 (alarm.getAlarmTime3() / SEC_PER_HOUR * SEC_PER_HOUR
					+ (alarm.getAlarmTime3() + SEC_PER_MIN) % SEC_PER_HOUR);
			scheduleEvent(NOW, new Integer(alarm.getAlarmTime3() / SEC_PER_MIN));
		}
	}
}

